package com.zx.sercurity;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;

import androidx.lifecycle.Lifecycle;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * 风控管理
 * 包含一次性的检测、循环类型的检测、触发类型的检测（弃用
 */
public class RiskControlManager {
    //单例
    private static RiskControlManager instance;
    //一次性的检测
    private final List<RiskControlInterface<?>> riskControls = new ArrayList<>();
    //循环或需要等待类型的检测
    private final List<AsyncRiskInterface<?>> riskInterfaces = new ArrayList<>();

    private final List<RiskListener> riskListeners = new ArrayList<>();
    private final List<AsyncRiskListener> asyncRiskListeners = new ArrayList<>();
    private final Handler handler = new Handler(Looper.getMainLooper());

    public static RiskControlManager getInstance() {
        if (instance == null) {
            synchronized (RiskControlManager.class) {
                if (instance == null) {
                    instance = new RiskControlManager();
                }
            }
        }
        return instance;
    }

    private RiskControlManager() {
        //一次性检测
        riskControls.add(new SimRisk());
        riskControls.add(new EmulatorRisk());
        riskControls.add(new DebugModeRisk());
        riskControls.add(new AccessibilityServiceRisk());
        riskControls.add(new MTRisk());
        riskControls.add(new NetProxyRisk());
        riskControls.add(new VPNRisk());
        riskControls.add(new CustomCertificatesRisk());
        riskControls.add(new ApplicationRisk());
        riskControls.add(new RootRisk());

        //非一次性的检测
        AsyncRiskListener asyncRiskListenerBus = new AsyncRiskListener() {
            @Override
            public void onAsyncRiskStateChange(AsyncResultWrapper<?> asyncResultWrapper) {

                for (AsyncRiskListener asyncRiskListener : asyncRiskListeners) {
                    asyncRiskListener.onAsyncRiskStateChange(asyncResultWrapper);
                }

            }

            @Override
            public void onFindAsyncRisk(AsyncResultWrapper<?> asyncResultWrapper) {

                for (AsyncRiskListener asyncRiskListener : asyncRiskListeners) {
                    asyncRiskListener.onFindAsyncRisk(asyncResultWrapper);
                }

            }
        };
        riskInterfaces.add(new MovementDetectorRiskCountDown(asyncRiskListenerBus));
        riskInterfaces.add(new BatteryRiskCountDown(asyncRiskListenerBus));
        riskInterfaces.add(new ChargingRiskCountDown(asyncRiskListenerBus));
        riskInterfaces.add(new RootAsyncRisk(asyncRiskListenerBus));
    }

    @SafeVarargs
    public final void exclude(Class<? extends RiskControlInterface<?>>... type) {
        Iterator<RiskControlInterface<?>> iterator = riskControls.iterator();
        while (iterator.hasNext()) {
            RiskControlInterface<?> next = iterator.next();
            for (Class<? extends RiskControlInterface<?>> actType : type) {
                if (actType.isInstance(next)) { // 检查 next 是否是 actType 的实例
                    iterator.remove(); // 移除该元素
                    break; // 找到匹配后跳出内层循环
                }
            }
        }
    }

    @SafeVarargs
    public final void excludeAsync(Class<? extends AsyncRiskInterface<?>>... type) {
        Iterator<AsyncRiskInterface<?>> iterator = riskInterfaces.iterator();
        while (iterator.hasNext()) {
            AsyncRiskInterface<?> next = iterator.next();
            for (Class<? extends AsyncRiskInterface<?>> actType : type) {
                if (actType.isInstance(next)) { // 检查 next 是否是 actType 的实例
                    iterator.remove(); // 移除该元素
                    break; // 找到匹配后跳出内层循环
                }
            }
        }
    }

    public ArrayList<RiskResult<?>> startRiskCheck(Context context) {
        return startRiskCheck(context, Collections.emptyList());
    }

    /**
     * 开始一次性的检测。
     * 这个检测会按顺序进行，当某一个检测结果不正常将立刻返回这个结果，此后的检测将会直接放弃
     *
     * @param context 上下文
     * @return 检测结果
     */
    public ArrayList<RiskResult<?>> startRiskCheck(Context context, List<Class<? extends RiskControlInterface<?>>> type) {
        //全部检测结果
        ArrayList<RiskResult<?>> allRisk = new ArrayList<>();
        ArrayList<RiskControlInterface<?>> copy = new ArrayList<>(riskControls);
        Iterator<RiskControlInterface<?>> iterator = copy.iterator();
        while (!type.isEmpty() && iterator.hasNext()) {
            RiskControlInterface<?> next = iterator.next();
            for (Class<? extends RiskControlInterface<?>> aClass : type) {
                if (aClass.isInstance(next)) {
                    iterator.remove();
                    break;
                }
            }
        }
        for (RiskControlInterface<?> riskControl : copy) {
            allRisk.add(riskControl.riskCheck(context));
        }
        for (RiskListener riskListener : riskListeners) {
            riskListener.onRisk(allRisk);
        }
        return allRisk;
    }

    /**
     * 开始异步性的检测
     *
     * @param context context
     */
    public void startAsyncRiskCheck(Context context) {
        for (AsyncRiskInterface<?> countDownAsyncRiskControl : riskInterfaces) {
            countDownAsyncRiskControl.beginCheck(context);
        }
    }

    /**
     * 开始异步性的检测
     *
     * @param context context
     */
    public void startAsyncRiskCheck(Context context, Lifecycle lifecycle) {
        for (AsyncRiskInterface<?> countDownAsyncRiskControl : riskInterfaces) {
            lifecycle.addObserver(countDownAsyncRiskControl);
            countDownAsyncRiskControl.beginCheck(context);
        }
    }

    /**
     * 关闭所以异步检查操作且无法再次启动检测
     */
    public void shutdownAllSyncRiskControl() {
        for (AsyncRiskInterface<?> countDownAsyncRiskControl : riskInterfaces) {
            countDownAsyncRiskControl.destroy();
        }
    }


    public void addRiskCheckListener(RiskListener riskListener) {
        riskListeners.add(riskListener);
    }

    public void removeRiskCheckListener(RiskListener riskListener) {
        riskListeners.remove(riskListener);
    }

    public void addAsyncRiskCheckListener(AsyncRiskListener riskListener) {
        asyncRiskListeners.add(riskListener);
    }

    public void removeAsyncRiskCheckListener(AsyncRiskListener riskListener) {
        asyncRiskListeners.remove(riskListener);
    }
}
